/*
 * 窗口容器
 * @author： 黄
 * 2018.4.21
 */

const { BrowserWindow } = require('electron')
const Conf = require('./config/config.js')
const path = require('path')
const log = require('electron-log')
/*
 * 简单说一下这个窗口的实现思路
 * 实现窗口容器思考了两种方式，第一种方式是通过在主进程中设置一个容器来存放对应的窗口，子进程通过electron自带的通讯方式和主进程容器进行通讯创建窗口
 * 优点：窗口统一归主进程创建，不依赖于外部浏览器，缺点：进程通讯异步创建窗口响应速度有待商榷
 * 第二种方式是把容器设置在浏览器localsrorage中，通过localstroage的同步属性来调用容器和保存窗口间传参
 * 优点：简单易用，同步方式，窗口间通讯方便，缺点：依赖于localstorage，主进程中不能使用
 * 目前先采用第二种方式，如果你有更好的方式可以联系我
 * 2374266244@qq.com
 */

class WindowBoxs {
    constructor() {
        this.freeWindowNum = 1 // 允许空闲的窗口数量
        // 基本的配置参数
        this.baseWindowConfig = {
            show: false,
            transparent: true,
            frame: false
        }
        // 初始化页面
        this.freePage = {
            model: 'shop',
            router: '/backGround'
        }
        this.isChecking = false
        this._windowList = []
        // list元素示例
        /*
         * {
         *   id: win.id,
         *   name: win.name,
         *   isUse: false // 是否使用
         *   model: model //模块
         *   router: router // 路由
         *   sendMsg: {} // 发送的数据
         *   backMsg: {} // 返回的数据
         * }
         */
        // 初始化窗口
        // this.init()
    }

    /*
     * 打开新的空白窗口等待加载
     */
    creatFreeWindow() {
        let win = new BrowserWindow(this.getWindowConfig())
        // 先把win.id存储起来防止销毁后无法获取
        let winId = win.id
        // 设置传参
        this._windowList.push({
            id: winId,
            name: '',
            isUse: false,
            model: this.freePage.model,
            router: this.freePage.router,
            sendMsg: {},
            backMsg: {}
        })

        let modalPath = process.env.NODE_ENV === 'development' ?
            'http://localhost:8080/' + this.freePage.model + '.html#' + this.freePage.router :
            path.join(Conf.root, 'html/dist/', this.freePage.model) + '.html#' + this.freePage.router

        win.loadURL(modalPath)

        win.on('close', function() {
            // 删除缓存
            this._windowList = this._windowList.filter(row => {
                return row.id != winId
            })
            win = null
        })
        // 窗口内容自适应大小
        win.on('resize', () => {
            const [width, height] = win.getContentSize()
            for (let wc of remote.webContents.getAllWebContents()) {
                // Check if `wc` belongs to a webview in the `win` window.
                if (wc.hostWebContents &&
                    wc.hostWebContents.id === win.webContents.id) {
                    wc.setSize({
                        normal: {
                            width: width,
                            height: height
                        }
                    })
                }
            }
        })
        return win
    }

    /*
     * 适配窗口参数
     */
    getWindowConfig() {
        if (process.env.NODE_ENV === 'development') {
            this.baseWindowConfig.webPreferences = { webSecurity: false }
        }
        return this.baseWindowConfig
    }

    /*
     * 平衡空白窗口数量
     */
    checkFreeWindow() {
        // 如果有缓存，查找空余窗口是否足够，不足的话创建到给定水平（同时删掉可能多出来的窗口）
        let notUseWindowNum = 0
        this._windowList.forEach(row => {
            if (!row.isUse) notUseWindowNum++
        })
        let num = this.freeWindowNum - notUseWindowNum
        if (num > 0) {
            for (var i = num; i > 0; i--) {
                this.creatFreeWindow() // 暂时循环调用，后期用延时
            }
        }
    }

    init() {
        log.info(123)
        this.checkFreeWindow()
    }


    /*
     * 使用一个空白窗口
     * 暂时支持初始几个参数
     * {width,height,model,router}
     */
    getFreeWindow(option) {
        // 怎么配置参数
        // 怎么绑定事件
        // 暂时支持简单的参数（width，height，frame, transform等）
        let freeWindowInfo = this._getFreeWindow()
        let freeWindow = BrowserWindow.fromId(freeWindowInfo.id)
        // 更新参数
        freeWindowInfo.router = option.url
        freeWindowInfo.sendMsg = option.data || {}
        freeWindowInfo.isUse = true
        // 重置窗口大小
        freeWindow.setSize(option.width, option.height)
        freeWindow.center()

        // 发送监听事件页面内跳转
        freeWindow.webContents.send('_changeModelPath', {
            url: option.url,
            windowInfo: freeWindowInfo
        })

        freeWindow.once('show', () => {
            // 窗口第一次显示的时候设置为已经使用，并且触发新增窗口函数
            this.setUseWindow(freeWindowInfo)
            this.checkFreeWindow()
        })
        return freeWindow
    }


    /*
     * 取出一个空白窗口并且返回（仅仅取出对象）
     */
    _getFreeWindow() {
        let freeWindow = this._windowList.filter(row => row.isUse == false)
        return freeWindow.length ? freeWindow[0] : false // 取一个
    }

    /*
     * 根据窗口id设置某一窗口为已使用
     */
    setUseWindow(freeWindowInfo) {
        this._windowList = this._windowList.map(row => {
            return row.id == freeWindowInfo.id ? freeWindowInfo : row
        })
    }
}

module.exports = new WindowBoxs()